package com.fzz.learnitservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.commonfzz.tools.IdGenerator;
import com.fzz.learnitservice.context.UserContext;
import com.fzz.learnitservice.mapper.ChatMemoryMapper;
import com.fzz.learnitservice.pojo.enums.ChatRoleEnum;
import com.fzz.learnitservice.pojo.po.ChatMemory;
import com.fzz.learnitservice.service.IAIService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class AIServiceImpl implements IAIService {
    private final ChatClient chatClient;
    private final ChatMemoryMapper chatMemoryMapper;


    private final IdGenerator idGenerator = new IdGenerator(12);
    
    private static final int MAX_HISTORY_PAIRS = 10; // 最多保留10轮对话（即20条消息）


    private static final String SYSTEM_PROMPT = "你是英语在线学习平台的专业助手（默认使用中文回答），" +
            "能够回答用户问题、帮助用户学习英语单词、语法和进行对话练习。";


    /**
     * 用户与AI对话，直接返回
     */
    public String chat(String question) {
        // 1️⃣ 从MySQL获取历史对话
        Long userId = UserContext.getUserId();
        List<ChatMemory> history = getHistoryFromMySQL(userId);

        // 2️⃣ 构建上下文消息
        List<Message> messages = new ArrayList<>();
        messages.add(new SystemMessage(SYSTEM_PROMPT)); // 提示词

        for (ChatMemory msg : history) {
            if (ChatRoleEnum.USER.getCode() == msg.getRole()) {
                messages.add(new UserMessage(msg.getContent()));
            } else {
                messages.add(new AssistantMessage(msg.getContent()));
            }
        }

        // 当前用户输入
        messages.add(new UserMessage(question));

        // 3️⃣ 调用 ChatClient
        String answer = chatClient.prompt()
                .messages(messages)
                .call()
                .content();

        // 4️⃣ 保存问答进MySQL
        saveMessageToMySQL(question, answer, userId);

        return answer;
    }

    /**
     * 流式聊天
     */
    public Flux<String> chatStream(String question, Long userId) {
        // 1️⃣ 从MySQL获取历史对话
        List<ChatMemory> history = getHistoryFromMySQL(userId);

        // 2️⃣ 构建上下文消息
        List<Message> messages = new ArrayList<>();
        messages.add(new SystemMessage(SYSTEM_PROMPT)); // 提示词

        for (ChatMemory msg : history) {
            if (ChatRoleEnum.USER.getCode() == msg.getRole()) {
                messages.add(new UserMessage(msg.getContent()));
            } else {
                messages.add(new AssistantMessage(msg.getContent()));
            }
        }

        // 当前用户输入
        messages.add(new UserMessage(question));

        // 3️⃣ 流式调用 ChatClient
        Flux<String> stream = chatClient.prompt()
                .messages(messages)
                .stream()
                .content();

        return stream.doOnComplete(() -> {

        });
    }

    /**
     * 流式聊天并发送SSE事件
     */
    @Override
    public void chatStreamWithSse(String question, SseEmitter emitter, Long userId) {
        // 异步处理流式响应
        CompletableFuture.runAsync(() -> {
            try {
                StringBuilder fullResponse = new StringBuilder();

                // 获取流式响应
                Flux<String> stream = chatStream(question, userId);

                stream.doOnNext(chunk -> {
                            try {
                                fullResponse.append(chunk);
                                emitter.send(SseEmitter.event()
                                        .data(chunk)
                                        .name("message"));
                            } catch (IOException e) {
                                emitter.completeWithError(e);
                            }
                        })
                        .doOnComplete(() -> {
                            try {

                                String fullAnswer = fullResponse.toString();
                                if (!fullAnswer.isEmpty()) {
                                    // 保存完整对话到MySQL
                                    saveMessageToMySQL(question, fullAnswer, userId);

                                }
                                log.info("AI接口调用成功, {}", fullAnswer);
                                emitter.complete();
                            } catch (Exception e) {
                                emitter.completeWithError(e);
                            }
                        })
                        .doOnError(error -> {
                            emitter.completeWithError(error);
                            log.error("AI接口调用失败, {}", error);
                        })
                        .subscribe();
            }
            catch (Exception e) {
                emitter.completeWithError(e);
            } finally {
                // 清理ThreadLocal，防止内存泄漏
                UserContext.clear();
            }
        });
    }

    /**
     * 清空会话
     */
    public void clearChatHistory() {
        Long userId = UserContext.getUserId();
        // 从MySQL删除该用户的所有对话记录
        LambdaQueryWrapper<ChatMemory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMemory::getUserId, userId);
        chatMemoryMapper.delete(wrapper);
    }

    /**
     * 查询用户的所有聊天记录
     * @return
     */
    @Override
    public List<ChatMemory> chatRecord() {
        Long userId = UserContext.getUserId();
        List<ChatMemory> result = getHistoryFromMySQL(userId);
        return result;
    }

    /**
     *
     * 编辑聊天（删除当前及之后的聊天记录并发送SSE事件）
     * @param question
     * @param emitter
     * @param userId
     * @param id
     */
    @Override
    public void edit(String question, SseEmitter emitter, Long userId, Long id) {
        // 异步处理流式响应
        CompletableFuture.runAsync(() -> {
            try {
                StringBuilder fullResponse = new StringBuilder();

                // 获取流式响应
                Flux<String> stream = chatStream(question, userId);

                stream.doOnNext(chunk -> {
                            try {
                                fullResponse.append(chunk);
                                emitter.send(SseEmitter.event()
                                        .data(chunk)
                                        .name("message"));
                            } catch (IOException e) {
                                emitter.completeWithError(e);
                            }
                        })
                        .doOnComplete(() -> {
                            try {

                                String fullAnswer = fullResponse.toString();
                                if (!fullAnswer.isEmpty()) {
                                    // 将当前及之后的对话删除
                                    this.deleteAfterMessage(userId, id);
                                    // 保存完整对话到MySQL
                                    this.saveMessageToMySQL(question, fullAnswer, userId);

                                }
                                log.info("AI接口调用成功, {}", fullAnswer);
                                emitter.complete();
                            } catch (Exception e) {
                                emitter.completeWithError(e);
                            }
                        })
                        .doOnError(error -> {
                            emitter.completeWithError(error);
                            log.error("AI接口调用失败, {}", error);
                        })
                        .subscribe();
            }
            catch (Exception e) {
                emitter.completeWithError(e);
            } finally {
                // 清理ThreadLocal，防止内存泄漏
                UserContext.clear();
            }
        });
    }

    /**
     * 将当前以及之后的对话删除
     * @param userId
     * @param id
     */
    private void deleteAfterMessage(Long userId, Long id) {
        // 1️⃣ 查询当前消息的创建时间
        ChatMemory currentMsg = chatMemoryMapper.selectById(id);
        if (currentMsg == null) {
            return; // 没找到消息直接返回
        }

        // 2️⃣ 构建删除条件：同一个用户，创建时间 >= 当前消息时间
        LambdaQueryWrapper<ChatMemory> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(ChatMemory::getUserId, userId)
                .ge(ChatMemory::getCreateTime, currentMsg.getCreateTime());

        // 3️⃣ 执行删除
        chatMemoryMapper.delete(deleteWrapper);
    }

    /**
     * 删除某个聊条记录
     * @param id
     */
    @Override
    public void delete(Long id) {
        ChatMemory chatMemory = chatMemoryMapper.selectById(id);

        LambdaQueryWrapper<ChatMemory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMemory::getUserId, chatMemory.getUserId())
                .eq(ChatMemory::getConversationId, chatMemory.getConversationId());

        chatMemoryMapper.delete(wrapper);
    }

    /**
     * 从MySQL获取历史对话记录
     */
    private List<ChatMemory> getHistoryFromMySQL(Long userId) {
        // 查询该用户的所有对话记录，按创建时间排序
        LambdaQueryWrapper<ChatMemory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMemory::getUserId, userId)
                .orderByAsc(ChatMemory::getCreateTime);
        
        List<ChatMemory> chatMemories = chatMemoryMapper.selectList(wrapper);
        
        // 限制最多返回10轮对话（20条消息）
        if (chatMemories.size() > MAX_HISTORY_PAIRS * 2) {
            int fromIndex = chatMemories.size() - MAX_HISTORY_PAIRS * 2;
            chatMemories = new ArrayList<>(chatMemories.subList(fromIndex, chatMemories.size()));
        }
        
        return chatMemories;
    }
    
    /**
     * 保存消息到MySQL
     */
    @Transactional
    public void saveMessageToMySQL(String question, String answer, Long userId) {

        Long conversationId = idGenerator.nextId();
        // 保存用户消息
        ChatMemory userChatMemory = ChatMemory.builder()
                .id(idGenerator.nextId())
                .role(ChatRoleEnum.USER.getCode())
                .conversationId(conversationId)
                .userId(userId)
                .content(question)
                .build();
        chatMemoryMapper.insert(userChatMemory);


        // 保存AI回复
        ChatMemory assistantChatMemory = ChatMemory.builder()
                .id(idGenerator.nextId())
                .role(ChatRoleEnum.ASSISTANT.getCode())
                .conversationId(conversationId)
                .userId(userId)
                .content(answer)
                .build();
        chatMemoryMapper.insert(assistantChatMemory);
        
        // 清理旧记录，只保留最新10轮对话（20条消息）
        cleanupOldMessages(userId);
    }
    
    /**
     * 清理旧消息，只保留最新10轮对话
     */
    private void cleanupOldMessages(Long userId) {
        // 查询该用户的所有记录数量
        LambdaQueryWrapper<ChatMemory> countWrapper = new LambdaQueryWrapper<>();
        countWrapper.eq(ChatMemory::getUserId, userId);
        Long count = chatMemoryMapper.selectCount(countWrapper);
        
        // 如果超过限制，删除最旧的记录
        if (count > MAX_HISTORY_PAIRS * 2) {
            // 查询需要保留的最新记录ID
            LambdaQueryWrapper<ChatMemory> selectWrapper = new LambdaQueryWrapper<>();
            selectWrapper.eq(ChatMemory::getUserId, userId)
                    .orderByDesc(ChatMemory::getCreateTime)
                    .last("LIMIT " + MAX_HISTORY_PAIRS * 2);
            List<ChatMemory> keepMessages = chatMemoryMapper.selectList(selectWrapper);
            
            // 获取需要保留的ID集合
            List<Long> keepIds = keepMessages.stream()
                    .map(ChatMemory::getId)
                    .collect(Collectors.toList());
            
            // 删除不在保留列表中的记录
            if (!keepIds.isEmpty()) {
                LambdaQueryWrapper<ChatMemory> deleteWrapper = new LambdaQueryWrapper<>();
                deleteWrapper.eq(ChatMemory::getUserId, userId)
                        .notIn(ChatMemory::getId, keepIds);
                chatMemoryMapper.delete(deleteWrapper);
            }
        }
    }
}
